package net.kleinhenz.norabase.client.datasource;

import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.smartgwt.client.data.DSRequest;
import com.smartgwt.client.data.DSResponse;
import com.smartgwt.client.data.DataSourceField;
import com.smartgwt.client.data.fields.DataSourceIntegerField;
import com.smartgwt.client.data.fields.DataSourceTextField;
import com.smartgwt.client.rpc.RPCResponse;
import com.smartgwt.client.widgets.grid.ListGridRecord;

import java.util.List;
import java.util.Map;

import net.kleinhenz.norabase.shared.SortOrientation;
import net.kleinhenz.norabase.shared.TextMatchStyle;
import net.kleinhenz.norabase.shared.model.Champion;
import net.kleinhenz.norabase.shared.model.Relic;
import net.kleinhenz.norabase.shared.model.Rune;
import net.kleinhenz.norabase.shared.model.Spell;

public class BattlegroupDS extends RuneDS {

	private String battlegroupId = null;
	
    public BattlegroupDS(String battlegroupId) {
    	super();
    	this.battlegroupId = battlegroupId;
    	
    	// add fields taht extends the fieldset in RuneDS
        DataSourceField field;
        field = new DataSourceTextField ("startingAbilitiesString", "Starting Abilities");
        field.setRequired(true);
        field.setCanEdit(false);
        addField(field);
        
        field = new DataSourceTextField ("upgradeAbilitiesString", "Upgrade Abilities");
        field.setRequired(true);
        field.setCanEdit(false);
        addField(field);

        field = new DataSourceTextField ("races", "Races");
        field.setRequired(true);
        field.setCanEdit(false);
        addField(field);

        field = new DataSourceTextField ("classes", "Classes");
        field.setRequired(true);
        field.setCanEdit(false);
        addField(field);

        field = new DataSourceTextField ("size", "Size");
        field.setRequired(true);
        field.setCanEdit(false);
        addField(field);
        
        field = new DataSourceIntegerField ("maxrng", "Range (max)");
        field.setRequired(true);
        field.setCanEdit(false);
        addField(field);

        field = new DataSourceIntegerField ("minrng", "Range (min)");
        field.setRequired(true);
        field.setCanEdit(false);
        addField(field);

        field = new DataSourceIntegerField ("spd", "Speed");
        field.setRequired(true);
        field.setCanEdit(false);
        addField(field);

        field = new DataSourceIntegerField ("def", "Defense");
        field.setRequired(true);
        field.setCanEdit(false);
        addField(field);

        field = new DataSourceIntegerField ("dmg", "Damage");
        field.setRequired(true);
        field.setCanEdit(false);
        addField(field);

        field = new DataSourceIntegerField ("hp", "Hitpoints");
        field.setRequired(true);
        field.setCanEdit(false);
        addField(field);
        
        field = new DataSourceIntegerField ("cooldown", "Cooldown");
        field.setRequired(true);
        field.setCanEdit(false);
        addField(field);        
    }

    public String getBattlegroupId() {
    	return this.battlegroupId;
    }
    
    @SuppressWarnings("unchecked")
	@Override
    protected void executeFetch (final String requestId, final DSRequest request, final DSResponse response) {

    	if (getBattlegroupId()==null) {
    		
    		response.setData(new ListGridRecord[0]);
    		response.setTotalRows(0);
    		processResponse(requestId, response);
    	} else {
	    	
	    	// aquiring meta data
	    	final Map<String, SortOrientation> sortSpec = convertSortSpecifier(request.getSortBy());
	        final int startIndex = (request.getStartRow() < 0)?0:request.getStartRow();
	        final int endIndex = (request.getEndRow() == null)?-1:request.getEndRow();
	        final TextMatchStyle textMatchStyle = convertTextMatchStyle(request.getTextMatchStyle());
	        final Map<String, Object> criteria = request.getCriteria().getValues();
	        
	        // server connection
	        BattlegroupDSServiceAsync service = GWT.create (BattlegroupDSService.class);
	        service.fetch(startIndex, endIndex, sortSpec, textMatchStyle, criteria, getBattlegroupId(), 
	        		new AsyncCallback<List<Rune>>() {
	            public void onFailure(Throwable caught) {
	                response.setStatus(RPCResponse.STATUS_FAILURE);
	                processResponse(requestId, response);
	            }
	            public void onSuccess(List<Rune> result) {
	                ListGridRecord[] list = new ListGridRecord[result.size()];
	                if (result.size() > 0) {
	                    for (int i = 0; i < result.size(); i++) {
	                        ListGridRecord record = new ListGridRecord ();
	                        copyValues(result.get(i), record);
	                        list[i] = record;
	                    }
	                }
	                response.setData(list);
	                // IMPORTANT: for paging to work we have to specify size of full result set
	                response.setTotalRows(result.size());
	                processResponse(requestId, response);
	            }
	        });
    	}
    }

    @Override
    protected void executeAdd (final String requestId, final DSRequest request, final DSResponse response) {
        JavaScriptObject data = request.getData();
        ListGridRecord rec = new ListGridRecord(data);
        BattlegroupDSServiceAsync service = GWT.create(BattlegroupDSService.class);
        service.add(rec.getAttributeAsInt("id"), rec.getAttributeAsString("type"), getBattlegroupId(), new AsyncCallback<Rune>() {
            public void onFailure (Throwable caught) {
                response.setStatus (RPCResponse.STATUS_FAILURE);
                processResponse (requestId, response);
            }
            public void onSuccess (Rune result) {
                ListGridRecord[] list = new ListGridRecord[1];
                ListGridRecord newRec = new ListGridRecord();
                copyValues(result, newRec);
                list[0] = newRec;
                response.setData(list);
                processResponse(requestId, response);
            }
        });
    }

    /*
    @Override
    protected void executeUpdate (final String requestId, final DSRequest request, final DSResponse response) {
        ListGridRecord rec = getEditedRecord (request);
        Rune testRec = new Rune();
        copyValues(rec, testRec);
        BattlegroupDSServiceAsync service = GWT.create(BattlegroupDSService.class);
        service.update(testRec, getBattlegroupId(), new AsyncCallback<Rune>() {
            public void onFailure(Throwable caught) {
                response.setStatus(RPCResponse.STATUS_FAILURE);
                processResponse(requestId, response);
            }
            public void onSuccess(Rune result) {
                ListGridRecord[] list = new ListGridRecord[1];
                ListGridRecord updRec = new ListGridRecord();
                copyValues(result, updRec);
                list[0] = updRec;
                response.setData(list);
                processResponse(requestId, response);
            }
        });
    }
	*/

    @Override
    protected void executeRemove(final String requestId, final DSRequest request, final DSResponse response) {
        JavaScriptObject data = request.getData();
        final ListGridRecord rec = new ListGridRecord(data);
        BattlegroupDSServiceAsync service = GWT.create(BattlegroupDSService.class);
        service.remove(rec.getAttributeAsInt("id"), rec.getAttributeAsString("type"), getBattlegroupId(), new AsyncCallback<Rune> () {
            public void onFailure(Throwable caught) {
                response.setStatus(RPCResponse.STATUS_FAILURE);
                processResponse(requestId, response);
            }
            public void onSuccess(Rune result) {
                ListGridRecord[] list = new ListGridRecord[1];
                // We do not receive removed record from server.
                // Return record from request.
                list[0] = rec;
                response.setData(list);
                processResponse(requestId, response);
            }

        });
    }
    
    @Override
	protected void copyValues(Rune from, ListGridRecord to) {

		super.copyValues(from, to);

		if (from instanceof Champion) {
			Champion fromC = (Champion)from;
			to.setAttribute("startingAbilitiesString", fromC.getStartingAbilitiesString());
			to.setAttribute("upgradeAbilitiesString", fromC.getUpgradeAbilitiesString());
			to.setAttribute("races", fromC.getRaces());
			to.setAttribute("classes", fromC.getClasses());
			to.setAttribute("size", fromC.getSize());
			to.setAttribute("maxrng", fromC.getMaxrng());
			to.setAttribute("minrng", fromC.getMinrng());
			to.setAttribute("spd", fromC.getSpd());
			to.setAttribute("dmg", fromC.getDmg());
			to.setAttribute("def", fromC.getDef());
			to.setAttribute("hp", fromC.getHp());
		} else if (from instanceof Relic) {
			Relic fromC = (Relic)from;			
			to.setAttribute("def", fromC.getDef());
			to.setAttribute("hp", fromC.getHp());
		} else 	if (from instanceof Spell) {
			Spell fromC = (Spell)from;
			to.setAttribute("desc", fromC.getDesc());
			to.setAttribute("cooldown", fromC.getCooldown());
		}
    }
}
